package top.dyzmj.detty.core.buffer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * 描述: 缓冲区
 *
 * @author dongYu
 * @date 2021/11/11
 */
public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {

	/**
	 * 返回该缓冲区可以包含的字节数
	 */
	public abstract int capacity();

	/**
	 * 调整此缓冲区的容量。
	 * 如果 newCapacity 小于当前容量，则该缓冲区的内容将被截断；
	 * 如果 newCapacity 大于当前容量，则会在缓冲区中追加长度为 (newCapacity - currentCapacity) 的未指定数据。
	 *
	 * @param newCapacity 缓冲区调整后的容量
	 * @throws IllegalArgumentException 如果 {@code newCapacity} 大于 {@link #maxCapacity()} 则抛出此异常。
	 */
	public abstract ByteBuf capacity(int newCapacity);

	/**
	 * 返回此缓冲区的最大容量，该值提供了 {@link #capacity()} 的上线
	 */
	public abstract int maxCapacity();

	/**
	 * 返回创建此缓冲区的 {@link ByteBufAllocator}
	 */
	public abstract ByteBufAllocator alloc();

	/**
	 * 返回该缓冲区的字节序
	 */
	public abstract ByteOrder order();

	/**
	 * 如果该缓冲区是另一个缓冲区的包装器，则返回底层缓冲区实例
	 *
	 * @return 如果该缓冲区不是包装器，则返回空
	 */
	public abstract ByteBuf unwrap();

	/**
	 * 当且仅当该缓冲区是由 NIO 直接缓冲区支持时返回 true
	 */
	public abstract boolean isDirect();

	/**
	 * 返回该缓冲区的 {@code readerIndex}
	 */
	public abstract int readerIndex();

	/**
	 * 设置该缓冲区的 {@code readerIndex}
	 *
	 * @throws IndexOutOfBoundsException 当指定的{@code readerIndex} 小于0或者大于 this.writeIndex 会抛出此异常
	 */
	public abstract ByteBuf readerIndex(int readerIndex);

	/**
	 * 返回该缓冲区的 {@code writeIndex}
	 */
	public abstract int writerIndex();

	/**
	 * 设置该缓冲区的 {@code writeIndex}
	 *
	 * @throws IndexOutOfBoundsException 当指定的 {@code writeIndex} 小于当前缓冲区的 readerIndex
	 *                                   或者 大于当前缓冲区的 {@code capacity} 时会抛出此异常
	 */
	public abstract ByteBuf writerIndex(int writerIndex);

	/**
	 * 一次性设置 缓冲区的 {@code readerIndex} 和 {@code writeIndex}
	 */
	public abstract ByteBuf setIndex(int readerIndex, int writerIndex);

	/**
	 * 返回可读的字节数
	 * 它等于 {@code (this.writerIndex - this.readerIndex)}.
	 */
	public abstract int readableBytes();

	/**
	 * 返回可写的字节数
	 * 它等于 {@code (this.capacity - this.writerIndex)}.
	 */
	public abstract int writableBytes();

	/**
	 * 返回可写入字节的最大可能数目
	 * 它等于 {@code (this.maxCapacity - this.writerIndex)}.
	 */
	public abstract int maxWritableBytes();

	/**
	 * 当且仅当 {@code (this.writerIndex - this.readerIndex)} 大于 0 是返回 True
	 */
	public abstract boolean isReadable();

	/**
	 * 当且仅当该缓冲区包含等于或大于指定数量的元素时返回true
	 */
	public abstract boolean isReadable(int size);

	/**
	 * 当前仅当 {@code (this.capacity - this.writerIndex)} 大于 0 是返回 True
	 */
	public abstract boolean isWritable();

	/**
	 * 当且仅当该缓冲区有足够的空间允许写入指定数量的元素时返回true
	 */
	public abstract boolean isWritable(int size);

	/**
	 * 将该缓冲区的 readerIndex 和 writeIndex 设置为0。
	 * 这个方法与 {@link #setIndex(int, int) setIndex(0, 0)} 相同。
	 * <p>
	 * 注意：此方法的行为与 NIO缓冲区的行为不一样，NIO缓冲区为设置缓冲区的限制
	 * </p>
	 */
	public abstract ByteBuf clear();

	/**
	 * 扩展缓冲区容量 {@link #capacity()}以确保可写字节数等于或大于指定的值。
	 * 如果该缓冲区中有足够的可写字节，则该方法返回时没有任何副作用。
	 *
	 * @param minWritableBytes -期望的最小可写字节数
	 * @throws IndexOutOfBoundsException if writerIndex() + minWritableBytes > maxCapacity()。
	 */
	public abstract ByteBuf ensureWritable(int minWritableBytes);

	/**
	 * 获取此缓冲区中位于指定绝对索引处的字节。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于 0 或者 index + 大于当前缓冲区的 {@code capacity} 会抛出此异常
	 */
	public abstract byte getByte(int index);

	/**
	 * 获取此缓冲区中位于指定绝对索引处的32位整数。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于 0 或者 index + 大于当前缓冲区的 {@code capacity} 会抛出此异常
	 */
	public abstract int getInt(int index);

	/**
	 * 获取此缓冲区中指定绝对索引处的64位长整数。此方法不修改该缓冲区的readerIndex或writerIndex。
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0或索引+ 8大于this.capacity
	 */
	public abstract long getLong(int index);

	/**
	 * 从指定的绝对索引处开始将该缓冲区的数据传输到指定的目的地，直到目的地变为不可写。
	 * 这个方法基本上与getBytes(int, ByteBuf, int, int)相同，只是这个方法增加目标的writerIndex，增加传输的字节数，
	 * 而getBytes(int, ByteBuf, int, int)没有增加。
	 * 这个方法不会修改源缓冲区的readerIndex或writerIndex。
	 */
	public abstract ByteBuf getBytes(int index, ByteBuf dst);


	/**
	 * 从指定的绝对索引处开始将该缓冲区的数据传输到指定的目的地，直到目的地变为不可写。
	 * 这个方法基本上与getBytes(int, ByteBuf, int, int)相同，只是这个方法增加目标的writerIndex，增加传输的字节数，
	 * 而getBytes(int, ByteBuf, int, int)没有增加。
	 * 这个方法不会修改源缓冲区的readerIndex或writerIndex。
	 */
	public abstract ByteBuf getBytes(int index, ByteBuf dst, int length);

	/**
	 * 从指定的绝对索引处开始将该缓冲区的数据传输到指定的目的地，直到目的地变为不可写。
	 * 这个方法基本上与getBytes(int, ByteBuf, int, int)相同，只是这个方法增加目标的writerIndex，增加传输的字节数，
	 * 而getBytes(int, ByteBuf, int, int)没有增加。
	 * 这个方法不会修改源缓冲区的readerIndex或writerIndex。
	 *
	 * @param dstIndex 目标的第一个索引
	 * @param length   要传输的字节数
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0，如果指定的dstIndex小于0，如果index + length大于这个值，
	 *                                   或者 dstIndex + length 大于 dst.capacity，会抛出此异常
	 */
	public abstract ByteBuf getBytes(int index, ByteBuf dst, int dstIndex, int length);

	/**
	 * 从指定的绝对索引开始，将该缓冲区的数据传输到指定的目的地。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0或如果index + dst 长度大于 this.capacity，会抛出此异常
	 */
	public abstract ByteBuf getBytes(int index, byte[] dst);

	/**
	 * 从指定的绝对索引开始，将该缓冲区的数据传输到指定的目的地。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex
	 *
	 * @param dstIndex 目标的第一个索引
	 * @param length   要传输的字节数
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0，如果指定的dstIndex小于0，如果index + length大于这个值。
	 *                                   或者dstIndex + length大于dst.length，会抛出此异常
	 */
	public abstract ByteBuf getBytes(int index, byte[] dst, int dstIndex, int length);

	/**
	 * 从指定的绝对索引开始将缓冲区的数据传输到指定的目的地，直到目的地的位置达到其限制。当目标位置增加时，此方法不会修改该缓冲区的readerIndex或writerIndex。
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0或如果index + dst.remaining()大于  this.capacity, 会抛出此异常
	 */
	public abstract ByteBuf getBytes(int index, ByteBuffer dst);

	/**
	 * 从指定的绝对索引处开始将该缓冲区的数据传输到指定的流。此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @param length 要传输的字节数
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0或如果index + length 大于 this.capacity, 会抛出此异常
	 * @throws IOException               - 如果指定的流在I/O过程中抛出异常
	 */
	public abstract ByteBuf getBytes(int index, OutputStream out, int length) throws IOException;

	/**
	 * 在此缓冲区的指定绝对索引处设置指定的字节。指定值的24个高阶位被忽略。此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0 或 index + 1大于 this.capacity
	 */
	public abstract ByteBuf setByte(int index, int value);

	/**
	 * 在此缓冲区的指定绝对索引处设置指定的32位整数。此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0或index + 4大于this.capacity
	 */
	public abstract ByteBuf setInt(int index, int value);

	/**
	 * 从指定的绝对索引处开始将指定源缓冲区的数据传输到此缓冲区，直到源缓冲区变为不可读。
	 * 这个方法基本上与 {@link #setBytes(int, ByteBuf, int, int)} 相同，只是这个方法增加源缓冲区的readerIndex，增加传输字节的数量，
	 * 而setBytes(int, ByteBuf, int, int)没有增加。
	 * 此方法不会修改该缓冲区的 readerIndex 或 writerIndex。
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0或如果index + src。readableBytes大于 this.capacity
	 */
	public abstract ByteBuf setBytes(int index, ByteBuf src);

	/**
	 * 从指定的绝对索引处开始将指定源缓冲区的数据传输到此缓冲区。
	 * 这个方法基本上与 {@link #setBytes(int, ByteBuf, int, int)} 相同，只是这个方法增加源缓冲区的readerIndex，增加传输字节的数量，
	 * 而setBytes(int, ByteBuf, int, int)没有增加。此方法不会修改该缓冲区的readerIndex或writerIndex
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0，如果index + length大于这个值，或者如果length大于src.readableBytes
	 */
	public abstract ByteBuf setBytes(int index, ByteBuf src, int length);

	/**
	 * 从指定的绝对索引处开始将指定源缓冲区的数据传输到此缓冲区。这个方法不会修改源和目标的readerIndex或writerIndex。
	 *
	 * @param srcIndex 源的第一个索引
	 * @param length   要传输的字节数
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0，如果指定的srcIndex小于0; 如果index + length大于这个值; 如果srcIndex + length大于src.capacity
	 */
	public abstract ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length);

	/**
	 * 从指定的绝对索引处开始将指定源数组的数据传输到此缓冲区。此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0或如果index + src.length 大于 this.capacity
	 */
	public abstract ByteBuf setBytes(int index, byte[] src);

	/**
	 * 从指定的绝对索引处开始将指定源数组的数据传输到此缓冲区。此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0；
	 *                                   如果指定的srcIndex小于0；
	 *                                   如果index + length大于这个值；
	 *                                   如果srcIndex + length大于src.length，则返回srcIndex + length
	 */
	public abstract ByteBuf setBytes(int index, byte[] src, int srcIndex, int length);

	/**
	 * 从指定的绝对索引处开始将指定源缓冲区的数据传输到此缓冲区，直到源缓冲区的位置达到其极限。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0或如果index + src.remaining()大于this.capacity
	 */
	public abstract ByteBuf setBytes(int index, ByteBuffer src);

	/**
	 * 从指定的绝对索引处开始将指定源流的内容传输到此缓冲区。此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @return 从指定通道读入的实际字节数。如果指定的通道被关闭的话则会返回-1
	 * @throws IndexOutOfBoundsException 如果指定的索引小于0或如果index + length大于this.capacity
	 * @throws IOException               如果指定的流在I/O过程中抛出异常
	 */
	public abstract int setBytes(int index, InputStream in, int length) throws IOException;

	/**
	 * 获取当前 {@code readerIndex} 处的一个字节，并在此缓冲区将 {@code readerIndex} 的值增加 {@code 1}
	 *
	 * @throws IndexOutOfBoundsException 如果 {@code this.readableBytes} 小 {@code 1} 的话
	 */
	public abstract byte readByte();

	/**
	 * 在当前readerIndex处获取一个32位整数，并在此缓冲区中将readerIndex增加4。
	 *
	 * @throws IndexOutOfBoundsException 如果 {@code this.readableBytes} 小 {@code 4} 的话
	 */
	public abstract int readInt();

	/**
	 * 从当前readerIndex开始，将该缓冲区的数据传输到指定的目标，直到目标变为不可写，并根据传输的字节数增加readerIndex。
	 * 这个方法与{@link #readBytes(ByteBuf, int, int)}基本相同，只是这个方法增加目标的writerIndex，增加传输的字节数，而readBytes(ByteBuf, int, int)则不增加。
	 *
	 * @throws IndexOutOfBoundsException 如果dst.writableBytes大于 this.readableBytes
	 */
	public abstract ByteBuf readBytes(ByteBuf dst);

	/**
	 * 从当前readerIndex开始，将该缓冲区的数据传输到指定的目的地，并将readerIndex增加传输的字节数(= length)。
	 * 这个方法与readBytes(ByteBuf, int, int)基本相同，只是这个方法增加目标的writerIndex，增加传输的字节数(= length)，而readBytes(ByteBuf, int, int)则没有。
	 *
	 * @throws IndexOutOfBoundsException 如果{@code length} 大于 this.readableBytes 或如果 {@code length}大于 dst.writableBytes
	 */
	public abstract ByteBuf readBytes(ByteBuf dst, int length);

	/**
	 * 从当前readerIndex开始，将该缓冲区的数据传输到指定的目的地，并将readerIndex增加传输的字节数(= length)
	 *
	 * @throws IndexOutOfBoundsException -如果指定的 dstIndex小于0，如果length大于this.readableBytes，或者dstIndex + length大于dst.capacity
	 */
	public abstract ByteBuf readBytes(ByteBuf dst, int dstIndex, int length);

	/**
	 * 从当前readerIndex开始，将该缓冲区的数据传输到指定的目的地，并增加readerIndex的传输字节数(= dst.length)。
	 *
	 * @throws IndexOutOfBoundsException 如果 {@code dst.length} 大于 {@code this.readableBytes}
	 */
	public abstract ByteBuf readBytes(byte[] dst);

	/**
	 * 从当前readerIndex开始，将该缓冲区的数据传输到指定的目的地，并将readerIndex增加传输的字节数(= length)。
	 *
	 * @throws IndexOutOfBoundsException 如果指定的dstIndex小于0；如果length大于this.readableBytes；
	 *                                   或者dstIndex + length大于dst.length
	 */
	public abstract ByteBuf readBytes(byte[] dst, int dstIndex, int length);

	/**
	 * 从当前readerIndex开始，将该缓冲区的数据传输到指定的目的地，直到目的地的位置达到其限制，并将readerIndex增加传输的字节数。
	 *
	 * @throws IndexOutOfBoundsException 如果 {@code dst.remaining} 大于 {@code this.readableBytes}
	 */
	public abstract ByteBuf readBytes(ByteBuffer dst);

	/**
	 * 将该缓冲区的数据传输到从当前readerIndex开始的指定流。
	 *
	 * @param length 要传输的字节数
	 * @throws IndexOutOfBoundsException 长度如果大于 this.readableBytes
	 * @throws IOException               如果指定的流在I/O过程中抛出异常
	 */
	public abstract ByteBuf readBytes(OutputStream out, int length) throws IOException;

	/**
	 * 在当前 {@code writerIndex} 处设置指定的字节，并在此缓冲区中将 {@code writerIndex} 增加1。
	 * 指定值的24个高阶位被忽略。如果 {@code this.writableBytes}小于1，{@link #ensureWritable(int)}将被调用，尝试扩展容量以适应
	 *
	 * @throws IndexOutOfBoundsException 如果 {@code this.writableBytes} 小于
	 */
	public abstract ByteBuf writeBytes(int value);

	/**
	 * 在当前 {@code writerIndex} 处设置指定的32位整数，并在此缓冲区中将 {@code writerIndex} 增加4。
	 * 如果 {@code this.writableBytes}小于4，{@link #ensureWritable(int)}将被调用，尝试扩展容量以适应
	 */
	public abstract ByteBuf writeInt(int value);

	/**
	 * 从当前writerIndex开始将指定的源缓冲区的数据传输到这个缓冲区，直到源缓冲区变得不可读，并将writerIndex增加传输的字节数
	 * 该方法与 {@link #writeBytes(ByteBuf, int, int)} 基本相同，只是该方法增加源缓冲区的readerIndex，增加传输字节数，
	 * 而 {@link #writeBytes(ByteBuf, int, int)} 则不增加。如果 this.writableBytes 小于 src.readableBytes, ensureWritable(int)将被调用，试图扩展容量以适应。
	 */
	public abstract ByteBuf writeBytes(ByteBuf src);

	/**
	 * 从当前writerIndex处开始将指定源缓冲区的数据传输到该缓冲区，并将writerIndex增加传输的字节数(= length)。
	 * 该方法与{@link #writeBytes(ByteBuf, int, int)}基本相同，只是该方法增加源缓冲区的readerIndex，增加传输字节数(= length)，
	 * 而{@link #writeBytes(ByteBuf, int, int)}则不增加。如果 {@code this.writableBytes} 小于 {@code length}, {@link #ensureWritable(int)}将被调用，试图扩展容量以适应。
	 */
	public abstract ByteBuf writeBytes(ByteBuf src, int length);

	/**
	 * 从当前writerIndex处开始将指定源缓冲区的数据传输到该缓冲区，并将writerIndex增加传输的字节数(= length)。如果这一点。writableBytes小于length, ensureWritable(int)将被调用，试图扩展容量以适应
	 *
	 * @throws IndexOutOfBoundsException -如果指定的srcIndex小于0，或者如果srcIndex + length大于src.capacity
	 */
	public abstract ByteBuf writeBytes(ByteBuf src, int srcIndex, int length);

	/**
	 * 将指定源数组的数据从当前writerIndex处传输到这个缓冲区，并将writerIndex增加传输的字节数(= src.length)。
	 * 如果this.writableBytes小于src.length，ensureWritable(int)将被调用，试图扩展容量以适应。
	 */
	public abstract ByteBuf writeBytes(byte[] src);

	/**
	 * 从当前 {@code writerIndex} 处开始将指定源数组的数据传输到这个缓冲区，并将 {@code writerIndex}增加传输的字节数(= length)。
	 * 如果 this.writableBytes小于length, ensureWritable(int)将被调用，试图扩展容量以适应
	 */
	public abstract ByteBuf writeBytes(byte[] src, int srcIndex, int length);

	/**
	 * 从当前writerIndex开始将指定源缓冲区的数据传输到该缓冲区，直到源缓冲区的位置达到其限制，并将writerIndex增加传输的字节数。
	 * 如果this.writableBytes小于src.remaining()， ensureWritable(int)将被调用，试图扩展容量以适应。
	 */
	public abstract ByteBuf writeBytes(ByteBuffer src);

	/**
	 * 将指定流的内容从当前writerIndex处传输到此缓冲区，并将writerIndex增加传输的字节数。
	 * 如果this.writableBytes小于length, ensureWritable(int)将被调用，试图扩展容量以适应。
	 *
	 * @param length 要传输的字节数
	 * @return 从指定的流读取的字节数
	 * @throws IOException 如果指定的流在I/O过程中抛出异常
	 */
	public abstract int writeBytes(InputStream in, int length) throws IOException;

	/**
	 * 定位指定值在此缓冲区中的第一次出现。搜索从指定的fromIndex(包括)到指定的toIndex(排他)。
	 * 如果fromIndex大于toIndex，搜索将按照从fromIndex (排他)到toIndex (包括)的相反顺序执行。
	 * 请注意，较低的索引总是被包含，较高的索引总是被排除。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @return 如果找到第一个时间的绝对索引，没有则返回 -1
	 */
	public abstract int indexOf(int fromIndex, int toIndex, byte value);

	/**
	 * 定位指定值在此缓冲区中的第一次出现。
	 * 搜索从当前的readerIndex(包括)到当前的writerIndex(排除)。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @return 当前readerIndex与第一次出现(如果找到)之间的字节数, 没有则返回 -1
	 */
	public abstract int bytesBefore(byte value);

	/**
	 * 定位指定值在此缓冲区中的第一次出现。
	 * 搜索从当前readerIndex(包括)开始，并持续指定的 length。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @return 当前readerIndex与第一次出现(如果找到)之间的字节数, 没有则返回 -1
	 * @throws IndexOutOfBoundsException 如果 length 大于 this.readableBytes
	 */
	public abstract int bytesBefore(int length, byte value);

	/**
	 * 定位指定值在此缓冲区中的第一次出现。搜索从指定的索引(包括)开始，并持续指定的长度。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 *
	 * @return 在指定的索引和第一次出现(如果找到)之间的字节数。没有则返回 -1
	 * @throws IndexOutOfBoundsException 如果index + length大于 this.capacity
	 */
	public abstract int bytesBefore(int index, int length, byte value);

	/**
	 * 返回该缓冲区的可读字节的副本。
	 * 修改返回的缓冲区或该缓冲区的内容根本不会影响彼此。
	 * 这个方法与{@code copy(int， int)}相同。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 */
	public abstract ByteBuf copy();

	/**
	 * 返回该缓冲区的子区域的副本。
	 * 修改返回的缓冲区或该缓冲区的内容根本不会影响彼此。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 */
	public abstract ByteBuf copy(int index, int length);

	/**
	 * 返回由该缓冲区组成的NIO ByteBuffers的最大数目。
	 * 注意，nioBuffers()或nioBuffers(int, int)可能会返回较少数量的ByteBuffers。
	 */
	public abstract int nioBufferCount();

	/**
	 * 将该缓冲区的可读字节公开为NIO ByteBuffer。
	 * 返回的缓冲区共享或包含该缓冲区的复制内容，而更改返回的NIO缓冲区的位置和限制不会影响该缓冲区的索引和标记。
	 * 这个方法与buf.nioBuffer(buf.readerIndex()， buf.readableBytes())相同。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。请注意，如果这个缓冲区是动态的，并且它调整了容量，那么返回的NIO缓冲区将看不到这个缓冲区的变化。
	 *
	 * @throws UnsupportedOperationException 如果这个缓冲区不能创建一个与自己共享内容的ByteBuffer
	 * @see #nioBufferCount()
	 * @see #nioBuffers()
	 * @see #nioBuffers(int, int)
	 */
	public abstract ByteBuffer nioBuffer();

	/**
	 * 将该缓冲区的子区域公开为NIO ByteBuffer。
	 * 返回的缓冲区共享或包含该缓冲区的复制内容，而更改返回的NIO缓冲区的位置和限制不会影响该缓冲区的索引和标记。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 * 请注意，如果这个缓冲区是动态的，并且它调整了容量，那么返回的NIO缓冲区将看不到这个缓冲区的变化。
	 *
	 * @throws UnsupportedOperationException 如果这个缓冲区不能创建一个与自己共享内容的ByteBuffer
	 */
	public abstract ByteBuffer nioBuffer(int index, int length);

	/**
	 * 将该缓冲区的可读字节公开为NIO ByteBuffer的字节。
	 * 返回的缓冲区共享或包含该缓冲区的复制内容，而更改返回的NIO缓冲区的位置和限制不会影响该缓冲区的索引和标记。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 * 请注意，如果这个缓冲区是动态的，并且它调整了容量，那么返回的NIO缓冲区将看不到这个缓冲区的变化。
	 *
	 * @throws UnsupportedOperationException 如果这个缓冲区不能创建一个与自己共享内容的ByteBuffer
	 */
	public abstract ByteBuffer[] nioBuffers();

	/**
	 * 返回的缓冲区共享或包含该缓冲区的复制内容，而改变返回的NIO缓冲区的位置和限制不会影响该缓冲区的索引和标记。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 * 请注意，如果这个缓冲区是动态的，并且它调整了容量，那么返回的NIO缓冲区将看不到这个缓冲区的变化。
	 *
	 * @throws UnsupportedOperationException 如果这个缓冲区不能创建一个与自己共享内容的ByteBuffer
	 */
	public abstract ByteBuffer[] nioBuffers(int index, int length);

	/**
	 * 当且仅当该缓冲区具有指向后备数据的底层内存地址的引用时返回true。
	 */
	public abstract boolean hasMemoryAddress();

	/**
	 * 返回指向支持数据的第一个字节的低级内存地址。
	 *
	 * @throws UnsupportedOperationException 如果这个缓冲区不支持访问低级内存地址
	 */
	public abstract long memoryAddress();

	/**
	 * 返回从该缓冲区的内容计算的哈希码。
	 * 如果有一个字节数组等于这个数组，两个数组应该返回相同的值
	 */
	@Override
	public abstract int hashCode();

	/**
	 * 将此缓冲区的可读字节解码为具有指定字符集名称的字符串。
	 * 这个方法与buf.toString(buf.readerIndex()， buf.readableBytes()， charsetName)相同。
	 * 此方法不修改此缓冲区的readerIndex或writerIndex。
	 */
	@Override
	public abstract String toString();

	@Override
	public abstract ReferenceCounted retain();

	@Override
	public abstract ReferenceCounted retain(int increment);

	@Override
	public abstract ReferenceCounted touch();

	@Override
	public abstract ReferenceCounted touch(Object hint);

	/**
	 * {@link AbstractByteBuf#ensureAccessible()}在内部使用，以防止在缓冲区释放后使用它(尽最大努力)。
	 *
	 * @return
	 */
	boolean isAccessible() {
		return refCnt() != 0;
	}

}
